package edu.mercer.sse.app;

import java.security.GeneralSecurityException;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableMap;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPSearchException;

import edu.mercer.sse.database.DBRecordSet;
import edu.mercer.sse.ldap.LDAPAddFunction;
import edu.mercer.sse.ldap.LDAPAddPredicate;
import edu.mercer.sse.ldap.LDAPDeleteFunction;
import edu.mercer.sse.ldap.LDAPDeletePredicate;
import edu.mercer.sse.ldap.LDAPOrgUnit;
import edu.mercer.sse.ldap.LDAPReviseFunction;
import edu.mercer.sse.ldap.LDAPRevisePredicate;
import edu.mercer.sse.ldap.LDAPValidateFunction;

public class DataSync
{
	private static Boolean _updateLDAP = false;
	
	private static StringBuilder _results = new StringBuilder();
	
	
	public static String preview() throws LDAPSearchException, 
										  LDAPException, 
										  GeneralSecurityException, 
										  SQLException
	{
		return runApp();
		
	}//method
	
	
	public static String publish() throws LDAPSearchException, 
										  LDAPException, 
										  GeneralSecurityException, 
										  SQLException
	{
		_updateLDAP = true;
		
		return runApp();
		
	}//method

	
	private static String runApp() throws LDAPSearchException, 
										  LDAPException, 
										  GeneralSecurityException, 
										  SQLException
	{
		/* clear string builder results */
		
		_results.delete(0, _results.length());

		/* run delete, revise, addition database->LDAP operations */
		
		_results.append( 
				dataSync(Collections2.filter( LDAPOrgUnit.getList(), 
											  new LDAPDeletePredicate() ),
											  
						new LDAPDeleteFunction()));

		_results.append( 
				dataSync(Collections2.filter( DBRecordSet.getData(), 
											  new LDAPAddPredicate() ),
											  
						new LDAPAddFunction()));

		_results.append( 
				dataSync(Collections2.filter( DBRecordSet.getData(), 
											  new LDAPRevisePredicate() ),
											  
						new LDAPReviseFunction()));
		
		return _results.toString();
		
	}//method


	private static String dataSync( 
			final Collection<ImmutableMap<String,String>> transactionsIn,
			final Function<Map<String, String>, Boolean> function )
	
			throws LDAPSearchException, 
				   LDAPException, 
				   GeneralSecurityException, 
				   SQLException
	{
		final StringBuilder results = new StringBuilder();

		Collection<ImmutableMap<String,String>> transactions = Collections2
				
				.transform( transactionsIn,
						
							new LDAPValidateFunction() );
		
		results.append( function.toString() + " effects: " 
				+ transactions.size() 
				+ " \n");

		Iterator<ImmutableMap<String,String>> ldapTxnsRecords = 
				transactions.iterator();

		while( ldapTxnsRecords.hasNext() ) results.append( 
				ldapTxnsRecords.next() + "\n" );

		if( _updateLDAP && transactions.size() > 0 )
		{
			final Collection<Boolean> txnResults = 

					Collections2.transform( transactions, 
							function );

			results.append("Results: \n");

			Integer okTally = 0;
			Integer failedTally  = 0;

			final Iterator<Boolean> txnResultsRecs = txnResults.iterator();

			while( txnResultsRecs.hasNext() )
			{
				if( txnResultsRecs.next().equals(true) ) okTally++;

				else failedTally++;

			}//while

			results.append("OK: "   + okTally + "\n" );
			results.append("Fail: " + failedTally  + "\n" );

		}//if		

		return results.toString();

	}//method

	
}//class
